package com.dianwoba.core.solr;

import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.regex.Pattern;

import org.apache.commons.lang.StringUtils;

import com.dianwoba.core.exception.SystemException;

/**
 * 条件类型枚举
 * @author 堵成杰
 * @since 2.0
 *
 */
public enum SolrConditionType {

	/**
	 * 等于: field:value
	 */
	EQ {
		public String getConditionInternal(String columnName, Object value) {
			return String.format("(%s:%s)",
					getTableDelimitedColunName(columnName),
					getConditionValue(value));
		}
	},
	
	/**
	 * 不等: -field:value
	 */
	NE {
		public String getConditionInternal(String columnName, Object value) {
			return String.format("-%s:%s",
					getTableDelimitedColunName(columnName),
					getConditionValue(value));
		}

		public boolean isNotCondition() {
			return true;
		}
	},
	
	/**
	 * 小于
	 */
	LT {
		
		public String getConditionInternal(String columnName, Object value) {
			return getTableDelimitedColunName(columnName) + ":{* TO "
					+ getConditionValue(value) + "}";
		}

		public String getCondition(String columnName, Object value,
				Object anotherValue) {
			return getTableDelimitedColunName(columnName) + ":{"
					+ getConditionValue(anotherValue) + " TO "
					+ getConditionValue(value) + "}";
		}

		public boolean isCompare() {
			return true;
		}

	},
	/**
	 * 小于等于
	 */
	LE {

		public String getConditionInternal(String columnName, Object value) {
			return getTableDelimitedColunName(columnName) + ":[* TO "
					+ getConditionValue(value) + "]";
		}

		public boolean isCompare() {
			return true;
		}

		public String getCondition(String columnName, Object value,
				Object anotherValue) {
			return getTableDelimitedColunName(columnName) + ":["
					+ getConditionValue(anotherValue) + " TO "
					+ getConditionValue(value) + "]";
		}

	},
	/**
	 * 大于
	 */
	GT {

		public String getConditionInternal(String columnName, Object value) {
			return getTableDelimitedColunName(columnName) + ":{"
					+ getConditionValue(value) + " TO *}";
		}

		public String getCondition(String columnName, Object value,
				Object anotherValue) {
			return getTableDelimitedColunName(columnName) + ":{"
					+ getConditionValue(value) + " TO "
					+ getConditionValue(anotherValue) + "}";
		}

		public boolean isCompare() {
			return true;
		}

	},
	/**
	 * 大于等于
	 */
	GE {

		public String getConditionInternal(String columnName, Object value) {
			return getTableDelimitedColunName(columnName) + ":["
					+ getConditionValue(value) + " TO *]";
		}

		public String getCondition(String columnName, Object value,
				Object anotherValue) {
			return getTableDelimitedColunName(columnName) + ":["
					+ getConditionValue(value) + " TO "
					+ getConditionValue(anotherValue) + "]";
		}

		public boolean isCompare() {
			return true;
		}
	},
	/**
	 * 包含: (field:value[0] OR field:value[1] OR ...)
	 *
	 */
	IN {

		public boolean isTarget(Object value) {
			return isTargetForIn("in", value);
		}

		
		public String getConditionInternal(String columnName, Object value) {
			return getInConditionInternal(
					getTableDelimitedColunName(columnName), value, "OR");
		}

		public int addValue(List<Object> paramList, Object value) {
			Object[] values = (Object[]) value;
			paramList.addAll(Arrays.asList(values));
			return values.length;
		}

		public boolean isMultiCondition() {
			return true;
		}
	},
	/**
	 * 不包含 ：NOT IN
	 *
	 */
	NOT_IN {

		public boolean isTarget(Object value) {
			return isTargetForIn("not in", value);
		}

		public String getConditionInternal(String columnName, Object value) {
			return "NOT "
					+ getInConditionInternal(
							getTableDelimitedColunName(columnName), value, "OR");
		}

		public int addValue(List<Object> paramList, Object value) {
			Object[] values = (Object[]) value;
			paramList.addAll(Arrays.asList(values));
			return values.length;
		}

		public boolean isNotCondition() {
			return true;
		}

		public boolean isMultiCondition() {
			return true;
		}
	},
	/**
	 * 模糊查询 LIKE ?* 
	 */
	LIKE {
	
		public String getConditionInternal(String columnName, Object value) {
			return String.format("%s:%s",
					getTableDelimitedColunName(columnName), getConditionValue(
							value, "*"));
		}
	};

	/**
	 * 替换类型字符串
	 */
	public final static String TABLE_REPLACE_WORD = "__TABLE_REPLACE_WORD__";
	/**
	 * 替换字段首字符串
	 */
	public final static String FIELD_REPLACE_WORD_FRONT = "__FIELD_";
	/**
	 * 替换字段尾字符串
	 */
	public final static String FIELD_REPLACE_WORD_BACK = "_FIELD__";
	/**
	 * 替换字段格式
	 */
	public final static Pattern FIELD_REPLACE_PATTERN = Pattern
			.compile(FIELD_REPLACE_WORD_FRONT + "(.+?)"
					+ FIELD_REPLACE_WORD_BACK);

	/**
	 * 添加替换类型字符串
	 * @param columnName
	 * @return
	 */
	protected String getTableDelimitedColunName(String columnName) {
		return TABLE_REPLACE_WORD + getFieldReplace(columnName);
	}

	/**
	 * 添加替换字段字符串
	 * @param columnName
	 * @return
	 */
	protected String getFieldReplace(String columnName) {
		return FIELD_REPLACE_WORD_FRONT + columnName + FIELD_REPLACE_WORD_BACK;
	}

	
	/**
	 * 取得solr查询条件字符串
	 * @param columnName	属性名称
	 * @param value			属性值
	 * @return				查询条件字符串
	 */
	public String getCondition(String columnName, Object value) {
		
		return getConditionInternal(columnName, value);
	}

	/**
	 * 是否为查询条件对象
	 * @param value
	 * @return
	 */
	public boolean isTarget(Object value) {
		if (value instanceof String && StringUtils.isEmpty((String) value)) {
			return false;
		}
		return value != null;
	}


	/**
	 * 追加属性值
	 * @param valueList
	 * @param value
	 * @return
	 */
	public int addValue(List<Object> valueList, Object value) {
		valueList.add(value);
		return 1;
	}

	/**
	 * 是否为包含对象的属性
	 * @param conditionName
	 * @param value
	 * @return
	 */
	protected boolean isTargetForIn(String conditionName, Object value) {
		Collection<?> values = null;
		if (value == null) {
			return false;
		} else if (value.getClass().isArray()) {
			values = Arrays.asList((Object[]) value);
		} else if (value instanceof Collection) {
			values = (Collection<?>) value;
		} else {
			throw new SystemException(conditionName);
		}
		if (values.isEmpty()) {
			return false;
		}
		for (Object element : values) {
			if (element != null) {
				return true;
			}
		}
		return false;
	}

	
	/**
	 * 取得in/not in查询字符串
	 * @param name
	 * @param value
	 * @param condition
	 * @return
	 */
	protected String getInConditionInternal(String name, Object value,
			String condition) {
		StringBuilder buf = new StringBuilder(30);
		buf.append("(");
		Object[] values = value instanceof Collection ? ((Collection<?>) value)
				.toArray() : Object[].class.cast(value);
		boolean first = true;
		for (Object element : values) {
			if (first) {
				first = false;
			} else {
				buf.append(" " + condition + " ");
			}
			if(element instanceof Collection){
				buf.append(getInConditionInternal(name, element, "AND"));
			}else{
				buf.append(name).append(":").append(getConditionValue(element));
			}
		}
		buf.append(")");
		return buf.toString();
	}


	/**
	 * 获取条件属性值
	 * @param value
	 * @return
	 */
	public String getConditionValue(Object value) {
		return getConditionValue(value, null);
	}


	/**
	 * 获取条件属性值
	 * @param value		条件属性
	 * @param append	后缀字符串
	 * @return
	 */
	public String getConditionValue(Object value, String append) {
		if (value == null) {
			return null;
		}
		String addValue = (append == null) ? StringUtils.EMPTY : append;

		if (value instanceof Date) {
			return SolrUtils.formatDate((Date) value);
		} else if (StringUtils.isNumeric(value.toString())) {
			return value.toString() + addValue;
		} else {
			return value.toString() + addValue;
		}
	}

	/**
	 * 是否包含大小比较
	 */
	public boolean isCompare() {
		return false;
	}

	/**
	 * 取得查询条件字符串
	 * @param columnName	字段名称
	 * @param value			属性值
	 * @param anotherValue	另一属性值
	 * @return
	 */
	public String getCondition(String columnName, Object value,
			Object anotherValue) {
		return null;
	}

	/**
	 * 是否否定条件
	 * @return
	 */
	public boolean isNotCondition() {
		return false;
	}

	/**
	 * 是否多条件
	 * @return 
	 */
	public boolean isMultiCondition() {
		return false;
	}

	public abstract String getConditionInternal(String columnName, Object value);

}
